const queue = require('async/queue');
const _ = require('lodash');
const nodemailer = require('nodemailer');

const Key = 'mail_queue:';

class MailQueue {
    constructor(app) {
        console.log('MailQueue constructor');
        let config = app.config;
        let sender = nodemailer.createTransport(config.mail);
        this.__app = app;
        this.__redis = app.redis;
        this.__queue = queue(async report_id => {
            const key = Key + report_id;
            let mission = await this.__redis.get(key);

            if (!mission) //redis中没有任务数据，中断发送过程
                return;

            let {bcc, appendContent} = JSON.parse(mission);

            if (_.isEmpty(bcc)) //没有收件人
                return this.del(report_id);


            let {subject, html} = await app.reportData.renderHtml(report_id, appendContent);
            let data = {from: config.mail.auth.user, bcc, subject, html};
            await new Promise((resolve, reject) => {
                sender.sendMail(data, err => {
                    if (err) {
                        console.log('发邮件失败', err);
                        this.__app.logger.error(err);
                        return reject(err);
                    }
                    console.log('成功发送邮件');
                    this.del(report_id);
                    this.__app.model.Report.update({email_sent: Date.now()}, {where: {id: report_id}});
                    resolve();
                });
            });
        }, 1);
        this.init();
    }

    /**
     * 将没有完成的任务继续完成
     * @returns {Promise<void>}
     * @private
     */
    async init() {
        let keys = await this.__redis.keys(Key + '*');
        console.log('mailQueue init 1', keys);
        if (keys.length === 0)
            return;
        let data = await this.__redis.mget(...keys);
        console.log('mailQueue init 2', data);
        _.each(data, value => {
            let {report_id} = JSON.parse(value);
            this.add({report_id}, false);
        });
    }


    get length() {
        return this.__queue.length();
    }

    /**
     * 添加任务到发送邮件的队列
     * @param report_id
     * @param bcc
     * @param appendContent
     * @param saveToRedis
     * @returns {Promise<void>}
     */
    async add({report_id, bcc, appendContent}, saveToRedis = true) {
        let mission = {report_id, bcc, appendContent};
        if (saveToRedis)
            await this.__redis.set(Key + report_id, JSON.stringify(mission, null));
        this.__queue.push(report_id);
    }

    /**
     * 获取日志报告的发送状态
     * state 状态:
     * 0 在队列等待中
     * 1 发送中
     * @param report_id
     * @returns {Promise<number>}
     */
    async get(report_id) {
        let res = await this.__redis.get(Key + report_id);
        if (!res)
            return null;
        return JSON.parse(res);
    }

    /**
     * 检查日志是否在队列中
     * @param report_id
     * @returns {Promise<boolean>}
     */
    async isExists(report_id) {
        return !!(await this.__redis.exists(Key + report_id));
    }

    /**
     * 更新队列中的数据
     * @param report_id
     * @param bcc
     * @param appendContent
     * @returns {Promise<void>}
     */
    async update({report_id, bcc, appendContent}) {
        await this.__redis.set(Key + report_id, JSON.stringify({report_id, bcc, appendContent}));
    }

    /**
     * 删除队列中的数据
     * @param report_id
     * @returns {Promise<void>}
     */
    async del(report_id) {
        await this.__redis.del(Key + report_id);
    }
}

module.exports = MailQueue;
